#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>

// 关键字: volatile易变关键字
//  volatile int flag = 0;
//  //加入volatile以后就会禁止编译器优化

// void handler(int signo)
// {
//     flag = 1;
//     printf("flag: 0->1\n");
// }

// int main()
// {
//     signal(2, handler);
//     printf("进程: %d\n", getpid());
//     while(!flag);
//     //该步骤(未优化):
//     //1、从内存中取数据放到cpu中
//     //2、进行判断

//     //步骤(编译器优化后):
//     //第一次将内存数据放入到CPU寄存器中以后就不在从内存中取数据了，而是直接作为一个cpu变量
//     //之后进行运算以后将运算之后的值返回内存，而内存中的值不变
//     //因为是对内存中的值进行检测，所以就无法正常结束进程
//     //这也就会导致CTRL + c后无法终止进程的原因
//     printf("进程结束!\n");
//     return 0;
// }

// SIGCHLD信号
// void handler(int signo)
// {
//     while (1)
//     {
//         pid_t rid = waitpid(-1, NULL, WNOHANG);//进行非阻塞等待
//         if (rid > 0)
//             printf("子进程: %d向父进程: %d发送信号: %d!\n", rid, getpid(), signo);
//         else if (rid < 0)
//             break;
//         else//rid == 0
//             break;
//     }
// }

int main()
{
    //场景1: 创建多个子进程时，多个子进程同时退出
    //解决方法: 用一个while循环让所有子进程一起退出
    //场景2: 创建多个子进程时，一部分退出，一部分不退出
    //解决方法:在场景1解决方法的前提下进行非阻塞等待

    // signal(SIGCHLD, handler);

    signal(SIGCHLD, SIG_IGN);//只在Linux上有用
    //自动回收所有子进程，不会产生僵尸进程

    pid_t id = fork();
    if (id == 0)
    {
        printf("我是子进程: %d\n", getpid());
        sleep(3);
        exit(0);
    }

    while (1)
    {
        printf("父进程: %d\n", getpid());
        sleep(1);
    }

    return 0;
}
